"""Define the Zabbix class, to obtain the zabbix information of hosts
in horizon by the zabbix rpc api.
Modified by haifengli(melonli@qq.com)
"""

#!/usr/bin/env python
# coding: utf-8
import os
import json
import string
import urllib2
from urllib2 import URLError
from gevent import monkey
from gevent.pool import Group
monkey.patch_all()
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
                      "openstack_dashboard.settings")

class Zabbix:
    """Define the Zabbix class, to obtain the zabbix information of hosts
    in horizon by the zabbix rpc api.
    """
    ggroup = Group()
    def __init__(self, rpc_api, username, passwd, hosts, ctl_eths, compute_eths):
        self.url = rpc_api
        self.username = username
        self.passwd = passwd
        self.hosts = hosts
        self.ctl_eths = ctl_eths
        self.compute_eths = compute_eths
        self.header = {'Content-Type': 'application/json'}
        self.auth_id = self._login()

    def _login(self):
        """Log in zabbix server, and return the token id."""
        data = json.dumps({
            "jsonrpc": "2.0",
            "method": "user.login",
            "params": {
                "user": self.username,
                "password": self.passwd},
            "id": 0
        })
        request = urllib2.Request(self.url, data)
        for key in self.header:
            request.add_header(key, self.header[key])
        try:
            result = urllib2.urlopen(request)
        except URLError as e:
            print 'Auth Failed', e.code
        else:
            response = json.loads(result.read())
            result.close()
            auth_id = response['result']
            print 'Auth Success!Auth ID is:::', auth_id
            return auth_id

    def get_data(self, data):
        """Get the data of specified type"""
        request = urllib2.Request(self.url, data)
        for key in self.header:
            request.add_header(key, self.header[key])
        try:
            result = urllib2.urlopen(request)
        except URLError as e:
            if hasattr(e, 'reason'):
                print 'We failed to reach a server.'
                print 'Reason: ', e.reason
            elif hasattr(e, 'code'):
                print 'The server could not fulfill the request.'
                print 'Error code: ', e.code
            return []
        else:
            response = json.loads(result.read())
            result.close()
            return response

    def get_hostgroup(self):
        """Get alll host group ID"""
        data = json.dumps({
            "jsonrpc": "2.0",
            "method": "hostgroup.get",
            "params": {
                "output": ["groupid", "name"]},
            "auth": self.auth_id,
            "id": 1})
        res = self.get_data(data)['result']
        print "Number Of Hosts: ", len(res)
        for group in res:
            print "Group ID:", group['groupid'], "\tGroupName:", group['name']

    def get_hostids(self, groupid):
        """Obtain the all host ids of the specified hostgroup."""
        data = json.dumps({
            "jsonrpc": "2.0",
            "method": "host.get",
            "params": {
                "output": "hostid",
                "groupids": groupid
            },
            "auth": self.auth_id,
            "id": 2
        })
        res = self.get_data(data)['result']
        hostids = []
        for i in range(len(res)):
            hostids.append(res[i]['hostid'])
        return hostids

    def get_hostsid(self):
        """Obtain the host id of the specified host."""
        data = json.dumps({
            "jsonrpc": "2.0",
            "method": "host.get",
            "params": {"output": ["hostid", "status", "host"]},
            "auth": self.auth_id,
            "id": 1})
        res = self.get_data(data)['result']
        hostsid = []
        if (res != 0) and (len(res) != 0):
            for host in res:
                if host['status'] == '1':
                    hostsid.append({host['host']:host['hostid']})
                elif host['status'] == '0':
                    hostsid.append({host['host']:host['hostid']})
                else:
                    pass
        return hostsid

    def get_hostgraph(self, hostname):
        """Get the graph and id of a host.
        Return the whole rs information including hostid.
        """
        data = json.dumps({
            "jsonrpc": "2.0",
            "method": "host.get",
            "params": {"selectGraphs": ["graphid", "name"],
                "filter": {"host": hostname}},
            "auth": self.auth_id,
            "id": 1})
        res = self.get_data(data)['result']
        return res[0]['graphs']

    def get_item(self, host):
        """Get the item."""
        data = json.dumps({
            "jsonrpc": "2.0",
            "method": "item.get",
            "params": {
                "output": ["name", "lastvalue", "key_"],
                "host": host,
                "sortfield": "name"
            },
            "auth": self.auth_id,
            "id": 2
        })
        res = self.get_data(data)
        if not res: return []
        return res['result']

    def get_info(self, host, parm=""):
        data = json.dumps({
            "jsonrpc": "2.0",
            "method": "item.get",
            "params": {
                "output": "extend",
                "host": host,
                "search": {"key_": parm }},
            "auth": self.auth_id,
            "id": 2})
        res = self.get_data(data)['result']
        if not res:
            return 0
        else:
            return res[0]['lastvalue']

    def get_cpu_usage(self, host):
        """Get the cpu usage of a host."""
        res = self.get_info(host, 'system.cpu.util[,idle]')
        if not res: return 0
        return round(100 - string.atof(res), 2)

    def get_available_memory(self, host):
        """Get the available memory."""
        res = self.get_info(host, 'vm.memory.size[available]')
        if not res: return 0
        return string.atoi(res)

    def get_total_memory(self, host):
        """Get the total memory of a host."""
        res = self.get_info(host, 'vm.memory.size[total]')
        if not res: return 0
        return string.atoi(res)

    def get_memory_usage(self, host):
        """Get the memory usage of a host."""
        available = self.get_available_memory(host)
        total = self.get_total_memory(host)
        if available and total:
            return 1 - string.atof(available)/string.atof(total)
        else:
            return 0

    def get_ingress_traffic(self, host):
        """Get the ingress traffic of a host."""
        res = self.get_item(host)
        if not res: return 0
        total = 0
        for value in res:
            if value['key_'].startswith('net.if.in'):
                total += string.atof(value['lastvalue'])
        return total

    def get_egress_traffic(self, host):
        """Get the egress traffic of a host."""
        res = self.get_item(host)
        if not res: return 0
        total = 0
        for value in res:
            if value['key_'].startswith('net.if.out'):
                total += string.atof(value['lastvalue'])
        return total

    def get_port_traffic(self, host, port):
        """Get the port traffic of a host, including ingress and egress."""
        key_in = 'net.if.in['+port+']'
        key_out = 'net.if.out['+port+']'
        res1 = self.get_info(host, key_in)
        res2 = self.get_info(host, key_out)
        if res1 or res2:
            res = string.atoi(res1)+string.atoi(res2)
            return res
        return 0

    def get_control_traffic(self, host):
        """Get the control traffic of a host."""
        traffic = [self.get_port_traffic(host, eth) for eth in self.ctl_eths]
        return sum(traffic)

    def get_compute_traffic(self, host):
        """Get the compute traffic of a host."""
        traffic = [self.get_port_traffic(host, eth) for eth in self.compute_eths]
        return sum(traffic)

    def get_all_compute_traffic(self):
        """Get all compute traffic."""
        return Zabbix.ggroup.map(self.get_compute_traffic, self.hosts)

    def get_all_control_traffic(self):
        """Get all control traffic."""
        return Zabbix.ggroup.map(self.get_control_traffic, self.hosts)

    def get_all_memory_usage(self):
        """Get all hosts memory usage."""
        return Zabbix.ggroup.map(self.get_memory_usage, self.hosts)

    def get_all_cpu_usage(self):
        """Get all hosts cpu usage."""
        return Zabbix.ggroup.map(self.get_cpu_usage, self.hosts)

    def get_all_info(self, info_types):
        """Get all information of all hosts according to the info_types."""
        return Zabbix.ggroup.map(self._get_all_info, info_types)

    def _get_all_info(self, info_type):
        """Get a type of information of all hosts according to the info_type."""
        methods = {'get_all_compute_traffic': self.get_all_compute_traffic,
                   'get_all_control_traffic': self.get_all_control_traffic,
                   'get_all_memory_usage': self.get_all_memory_usage,
                   'get_all_cpu_usage': self.get_all_cpu_usage}
        return methods[info_type]()

def main():
    rpc_api = 'http://192.168.100.3/api_jsonrpc.php'
    username = 'Admin'
    passwd = 'zabbix'
    hosts = ['compute'+str(i) for i in xrange(1, 13)]
    zbx = Zabbix(rpc_api, username, passwd, hosts, ['eth1'], ['com-balancing'])
    info_types = ['get_all_compute_traffic',
                  'get_all_control_traffic',
                  'get_all_memory_usage',
                  'get_all_cpu_usage']
    infos = zbx.get_all_info(info_types)
    for (host, compute_traffic, control_traffic,
            memory_usage, cpu_usage) in zip(hosts, *infos):
        print(host, compute_traffic, control_traffic, memory_usage, cpu_usage)

if __name__ == '__main__':
    main()
